﻿package poker;
//Essa classe contém métodos para detectar jogos em uma mão de poker.

public class Poker {

	// Construtor privado (nenhum objeto deve ser instanciado).
	private Poker() {
	}
	/*
	 * Métodos estáticos
	 */
	/* DONE: Métodos para reconhecer jogos em uma mão. */	
	/**Done
	 * findPair: Retorna true se encontrou um par, caso contrário false
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findPair(Card[] hand) {
		/*São 2 cartas iguais e três diferentes.
		 * 
		 */
		String carta_A_face, carta_B_face;
		int i;//primeira carta
		int j;//segunda carta
		for(i =0 ; i < 4;i++){
			for(j = i+1; j < 5; j++){//percorre sempre a carta seguinte a comparada
				carta_A_face = hand[i].GetFace();
				carta_B_face = hand[j].GetFace();
				if(carta_A_face == carta_B_face){// basta encontra duas cartas com mesmo valor(face)
					return true;				
				}
			}
		}
		return false;// terminou e não encontrou nada, então retorna false
	}
	/**Done
	 * findPair: Retorna true se encontrou dois pares, caso contrário false
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findTwoPairs(Card[] hand) {
		/*São 2 pares de cartas.
		 * 
		 */
		String carta_A_face, carta_B_face;
		int i;//primeira carta
		int j;//segunda carta
		int k = 0;//número de pares
		for(i = 0 ; i < 4; i++){
			for(j = i+1; j < 5; j++){//percorre sempre a carta seguinte a comparada
				carta_A_face = hand[i].GetFace();
				carta_B_face = hand[j].GetFace();
				if(carta_A_face == carta_B_face){// basta encontra duas cartas com mesmo valor(face)
					k++;
				}
			}
		}
		/*Não retorna 2 pares em FULL HOUSE!*/
		if(k == 2) return true;// uma mão deve pelo menos mais de um par para retornar true
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findThreeOfAKind(Card[] hand) {
		/*São 3 cartas iguais mais duas cartas diferentes.
		 * 
		 */
		String carta_A_face, carta_B_face;
		int i;//primeira carta
		int j;//segunda carta
		int k = 0;//número de pares
		for(i = 0 ; i < 4; i++){
			for(j = i+1; j < 5; j++){//percorre sempre a carta seguinte a comparada
				carta_A_face = hand[i].GetFace();
				carta_B_face = hand[j].GetFace();
				if(carta_A_face == carta_B_face){// basta encontra duas cartas com mesmo valor(face)
					k++;
				}
			}
		}
		if(k == 3){
			return true;// uma mão deve pelo menos mais de um par para retornar true
		}
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findStraight(Card[] hand) {
		/*São 5 cartas seguidas sem importar o naipe.
		 * 
		 */
		String faces[] = {"Dois", "Três", "Quatro", "Cinco", "Seis",
				"Sete", "Oito", "Nove", "Dez", "Valete", "Dama", "Rei", "Ás" };
		int i;
		String carta_1, carta_2, carta_3, carta_4, carta_5;
		hand = ordena(hand);//PRIMEIRO ORDENEI MINHA HAND ANTES DE PROCURAR ORDEM NELA
		carta_1 = hand[0].GetFace();//primeira carta
		carta_2 = hand[1].GetFace();//segunda carta
		carta_3 = hand[2].GetFace();//terceira carta
		carta_4 = hand[3].GetFace();//quarta carta
		carta_5 = hand[4].GetFace();//quinta carta
		i = 0;
		/*reduzimos o espaço de busca pelo fato da primeira carta estar dentro de um intervalo de valores possíveis: 2 até 10
		 * a segunda de 3 até J e assim sucessivamente  
		 */
		while(carta_1 != faces[i] && i < (faces.length-hand.length)) i++;
		if(carta_2 == faces[i+1] && carta_3 == faces[i+2] && carta_4 == faces[i+3] && carta_5 == faces[i+4])
			return true;
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findFlush(Card[] hand) {
		/*São 5 cartas do mesmo naipe sem serem seguidas. 
		 * 
		 */
		String carta_1, carta_2, carta_3, carta_4, carta_5;
		carta_1 = hand[0].GetSuit();//primeira carta
		carta_2 = hand[1].GetSuit();//segunda carta
		carta_3 = hand[2].GetSuit();//terceira carta
		carta_4 = hand[3].GetSuit();//quarta carta
		carta_5 = hand[4].GetSuit();//quinta carta
		if(carta_1 == carta_2 && carta_2 == carta_3 && carta_3 == carta_4 && carta_4 == carta_5) return true;
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findFullHouse(Card[] hand) {
		/*Uma trinca e um par.
		 * 
		 */
		String carta_A_face, carta_B_face;
		int i;//primeira carta
		int j;//segunda carta
		int k = 0;//número de pares
		for(i = 0 ; i < 4; i++){
			for(j = i+1; j < 5; j++){//percorre sempre a carta seguinte a comparada
				carta_A_face = hand[i].GetFace();
				carta_B_face = hand[j].GetFace();
				if(carta_A_face == carta_B_face){// basta encontra duas cartas com mesmo valor(face)
					k++;
				}
			}
		}
		if(k == 4){
			return true;// uma mão deve pelo menos mais de um par para retornar true
		}
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findFourOfAKind(Card[] hand) {
		/*São 5 cartas seguidas do mesmo naipe, 10 até ao As.
		 * 
		 */
		String carta_A_face, carta_B_face;
		int i;//primeira carta
		int j;//segunda carta
		int k = 0;//número de pares
		for(i = 0 ; i < 4; i++){
			for(j = i+1; j < 5; j++){//percorre sempre a carta seguinte a comparada
				carta_A_face = hand[i].GetFace();
				carta_B_face = hand[j].GetFace();
				if(carta_A_face == carta_B_face){// basta encontra duas cartas com mesmo valor(face)
					k++;
				}
			}
		}
		if(k == 6){
			return true;// uma mão deve exato 6 combinações da comparação para ser 4 iguais
		}
		else return false;
	}
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findStraightFlush(Card[] hand) {
		/*São 5 cartas seguidas do mesmo naipe que não seja do 10 até ao As.
		 * 
		 */
		String carta_1, carta_2, carta_3, carta_4, carta_5;
		carta_1 = hand[0].GetFace();//primeira carta
		carta_2 = hand[1].GetFace();//segunda carta
		carta_3 = hand[2].GetFace();//terceira carta
		carta_4 = hand[3].GetFace();//quarta carta
		carta_5 = hand[4].GetFace();//quinta carta
		int i = 0;
		String faces[] = {"Dois", "Três", "Quatro", "Cinco", "Seis",
				"Sete", "Oito", "Nove", "Dez", "Valete", "Dama", "Rei", "Ás" };
		if(Poker.findStraight(hand) == true && Poker.findFlush(hand)){
			while(carta_1 != faces[i] && i < (faces.length-hand.length)) i++;//olhar se a primeira carta esta de 2 até 9
			if(carta_2 == faces[i+1] && carta_3 == faces[i+2] && carta_4 == faces[i+3] && carta_5 == faces[i+4]) return true;
		}
		return false;
	}	
	/**Done
	 * @author raphael
	 * @param hand
	 * @return boolean
	 */
	public static boolean findRoyalFlush(Card[] hand) {
		/*São 5 cartas seguidas do mesmo naipe, 10 até ao As. 
		 * 
		 */
		String carta_1;
		carta_1 = hand[0].GetFace();//primeira carta
		if(Poker.findStraight(hand) == true && Poker.findFlush(hand) == true && carta_1 =="Dez") return true;//olhar se a primeira carta for 10!
		else return false;
	}
	/* TODO (opcional): Será permitido no máximo um método auxiliar privado. */
	public static Card[] ordena(Card[] hand){
		String[] faces = {"Dois", "Três", "Quatro", "Cinco", "Seis",
				"Sete", "Oito", "Nove", "Dez", "Valete", "Dama", "Rei", "Ás" };
		String[] suites = { "Paus", "Copas", "Espadas", "Ouros"};
		String face_A, face_B;
		String suite_A, suite_B;
		int i, j, k, index_A, index_B;
		index_A = index_B = -1;//Inicializei pois o Eclipse reclamou!
		Card temp;
		/*INSERTION SORT da HAND
		 * 
		 * Considere m_esquerda e m_direita, sendo as mão esquerda e direita que segura uma carta por vez do dequeue
		 * queremos que sempre a m_esquerda, esteja com valor menor e a m_direita com valor maior
		 * a princípio tiramos com a m_esquerda as cartas indo da primeira até a penúltima carta
		 * já a m_direita retira da segunda até a última carta
		 * então tiramos uma carta com a m_esquerda e vamos percorrendo o dequeue da esquerda para a direita com a
		 * m_direita que vai retirando na ordem e comparando com a m_esquerda
		 * não havendo necessidade de troca vamos passando para a próxima iteraçao até que a m_direita percorreu
		 * todas as cartas do dequeue(hand). Então a m_esquerda passa para o para a próxima iteração e assim sucessivamente
		 * até que m_esquerda chegue a quarta e m_direita a quinta carta do dequeue(hand)
		 * Neste caso i representa m_esquerda e j representa m_direita
		 *  
		 */
		for(i = 0; i < hand.length-1; i++){//compara indo da primeira até a quarta carta: 
			for(j = i+1;j < hand.length; j++){ //compara indo da segunda até última carta, sempre m_direita tem a carta posterior a atual m_esquerda
				face_A = hand[i].GetFace();
				face_B = hand[j].GetFace();
				for(k = 0; k < faces.length; k++){
					if(face_A == faces[k]) index_A = k;
					if(face_B == faces[k]) index_B = k;
				}
				/*terminou o for tenho um valor associado as cartas que estou comparando
				 * elas podem ser iguais: então tenho que comparar os naipes
				 *OBS: O ECLIPSE ACUSA index_A e index_B sem serem inicializados, MAS
				 * Saiu do laço anterior obrigatoriamente o index_A e index_B possuem um valor!
				 * A não ser que esta cartas não sejam do baralho!(ABSURDO)!
				 */
				/*CASO CARTAS MESMA FACE*/
				if(index_A == index_B){
					suite_A = hand[i].GetSuit();
					suite_B = hand[j].GetSuit();
					for(k = 0; k < suites.length; k++){
						if(suite_A == suites[k]) index_A = k;
						if(suite_B == suites[k]) index_B = k;	
					}
				}//terminou do caso cartas  com mesma face
				if(index_A > index_B){
					/*SWAP*/
					temp = hand[j];
					hand[j] = hand[i];
					hand[i] = temp;
				}
			}//FIM do for da j: M_DIREITA
		}//FIM do for da i: M_ESQUERDA
		return hand;
	}
	//Se ocorrerendo jogos, o melhor jogo é único!
	public enum BestGame{
		NENHUM,			//"NENHUM JOGO"
		PAIR,			//"Par "
		TWOPAIR,		//"Dois Pares"
		THREEOFKIND,		//"Trio",
		STRAIGHT,		//"Sequência",
		FLUSH, 			//"Flush",
		FULLHOUSE,		//"Full House",
		FOROFKIND,		//"Quadra",
		STRAIGHTFLUSH,	//"Sequência de mesmo naipe",
		ROYALFLUSH		//"Sequência Real de mesmo naipe"
	}
	public class EnumBestGame{
		BestGame jogo;
		public EnumBestGame(BestGame jogo){
			this.jogo = jogo;
		}
		public void ApresentaBestGame() {
	        switch (jogo) {
	            case PAIR:
	                System.out.println("Par.");
	                break;
	            case TWOPAIR:
	                System.out.println("Dois Pares.");
	                break;
	            case THREEOFKIND: 
	                System.out.println("Trio.");
	                break;
	            case STRAIGHT: 
	                System.out.println("Sequência.");
	                break;
	            case FLUSH:
	                System.out.println("Flush.");
	                break;
	            case FULLHOUSE:
	                System.out.println("Full House.");
	                break;
	            case FOROFKIND: 
	                System.out.println("Quadra.");
	                break;
	            case STRAIGHTFLUSH: 
	                System.out.println("Sequência de mesmo naipe.");
	                break;
	            case ROYALFLUSH: 
	                System.out.println("Sequência Real de mesmo naipe.");
	                break;
	            default:
	                System.out.println("NENHUM jogo detectado");
	                break;
	        }
	    }
		

	} 



} // fim classe Poker
